Operator overloading
2 Operator Overloading​
Introduction​
Operator overloading allows you to redefine the way operators work for user-defined types (classes and structs). It enables you to specify more intuitive ways to perform operations on objects of your classes.
Overloading an operator does not change:
- the operator precedence,
- the associativity of the operator,
- the arity of the operator, or
- the meaning of how the operator works on objects of built-in types.
Syntax​
An overloaded operator is implemented as a special member function with the keyword operator followed by the symbol of the operator being overloaded.
class ClassName {
public:
ReturnType operatorOpSymbol (ParameterList) {
// Function body
}
};
Example​
class Complex {
public:
double real, imag;
Complex(double r = 0, double i = 0) : real(r), imag(i) {}
// Overload the + operator
Complex operator+ (Complex& obj) {
return Complex(real + obj.real, imag + obj.imag);
}
};
Types of Operators that Can Be Overloaded​
- Arithmetic operators:
+,-,*,/,% - Relational operators:
==,!=,<,>,<=,>= - Logical operators:
&&,||,! - Bitwise operators:
&,|,^,~,<<,>> - Increment and decrement operators:
++,-- - Assignment operators:
=,+=,-=,*=,/=,%= - Subscript operator:
[] - Function call operator:
() - Member access operators:
->,.(only for pointers to members) - Input and output operators:
>>,<<
Operators that cannot be overloaded include: ::, .*, ., ? :, sizeof
Example:​
#include <iostream>
class Complex {
public:
double real, imag;
Complex(double r = 0, double i = 0) : real(r), imag(i) {}
// Overload the == operator
bool operator== (const Complex& obj) const {
return (real == obj.real && imag == obj.imag);
}
};
int main() {
Complex c1(3.0, 4.0), c2(3.0, 4.0);
if (c1 == c2) {
std::cout << "c1 and c2 are equal" << std::endl;
} else {
std::cout << "c1 and c2 are not equal" << std::endl;
}
return 0;
}
Operator Overloading Rules​
When overloading operators, there are several rules to keep in mind:
- Preserve the Operator's Original Meaning: The overloaded operator should make sense in the context of the operation it performs.
- Return Types: The return type should be appropriate for the operation. For example,
operator+should return a new object, whileoperator+=should return a reference to*this. - Symmetry: Ensure symmetric behavior where applicable. For example,
a == bshould return the same result asb == a. - Do Not Overload Operators Irrelevantly: Only overload operators that make sense for your class. For example, overloading the arithmetic operators for a class that represents a complex number makes sense, but overloading them for a class that represents a database connection does not.